home *** CD-ROM | disk | FTP | other *** search
- // C++-Example.c
- //
- // Included in the Alpha distribution as an example of the C++ mode
- //
- // source of original document:
- //
- // http://www.research.att.com/~bs
- //
- // copywrite (c) 1985 Bjarne Stroustrup
- // <bs@research.att.com>
-
-
- // The desk calculator
- //
- // reads from std::cin
- // uses namespaces, but no exceptions
- //
- // The C++ Programming Language, pp 163-171, sec 8.2, Namespaces
-
-
- // uses += rather than push_back() for string
- // to work around standard library bug
-
- // No guarantees offered. Constructive comments to bs@research.att.com
-
- /*
- program:
- END // END is end-of-input
- expr_list END
-
- expr_list:
- expression PRINT // PRINT is ';'
- expression PRINT expr_list
-
- expression:
- expression + term
- expression - term
- term
-
- term:
- term / primary
- term * primary
- primary
-
- primary:
- NUMBER
- NAME
- NAME = expression
- - primary
- ( expression )
- */
-
- #include<iostream>
- #include<map>
- #include<string>
- #include<cctype>
-
- // note: no "using namespace std;"
-
- namespace Error {
-
- int no_of_errors;
-
- double error(const char* s)
- {
- cerr << "error: " << s << '\n';
- no_of_errors++;
- return 1;
- }
- }
-
- namespace Lexer {
-
- enum Token_value {
- NAME, NUMBER, END,
- PLUS='+', MINUS='-', MUL='*', DIV='/',
- PRINT=';', ASSIGN='=', LP='(', RP=')'
- };
-
- Token_value curr_tok;
- double number_value;
- string string_value;
-
- Token_value get_token();
- }
-
-
- Lexer::Token_value Lexer::get_token()
- {
- char ch = 0;
- cin>>ch;
-
- switch (ch) {
- case 0:
- return END;
- case ';':
- return curr_tok=PRINT;
- case '*':
- case '/':
- case '+':
- case '-':
- case '(':
- case ')':
- case '=':
- return curr_tok=Token_value(ch);
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case '.':
- cin.putback(ch);
- cin >> number_value;
- return curr_tok=NUMBER;
- default: // NAME, NAME =, or error
- if (isalpha(ch)) { // warning isalpha is a macro
- // in some implementations
- std::cin.putback(ch);
- std::cin>>string_value;
- return curr_tok=NAME;
- }
- Error::error("bad token");
- return curr_tok=PRINT;
- }
- }
-
- map<string,double> table; // global; see sec9.???
-
- namespace Parser {
- double prim(bool get); // handle primaries
- double term(bool get); // multiply and divide
- double expr(bool get); // add and subtract
-
- using Lexer::get_token; // commonly used names
- using Lexer::curr_tok;
- using Error::error;
- }
-
- double Parser::prim(bool get) // handle primaries
- {
- if (get) get_token();
-
- switch (curr_tok) {
- case Lexer::NUMBER: // floating point constant
- get_token();
- return Lexer::number_value;
- case Lexer::NAME:
- { double& v = table[Lexer::string_value];
- if (get_token() == Lexer::ASSIGN) v = expr(1);
- return v;
- }
- case Lexer::MINUS: // unary minus
- return -prim(1);
- case Lexer::LP:
- { double e = expr(1);
- if (curr_tok != Lexer::RP) return error(") expected");
- get_token(); // eat ')'
- return e;
- }
- case Lexer::END:
- return 1;
- default:
- return error("primary expected");
- }
- }
-
- double Parser::term(bool get) // multiply and divide
- {
- double left = prim(get);
-
- for (;;)
- switch (curr_tok) {
- case Lexer::MUL:
- left *= prim(true);
- break;
- case Lexer::DIV:
- if (double d = prim(true)) {
- left /= d;
- break;
- }
- return error("divide by 0");
- default:
- return left;
- }
- }
-
- double Parser::expr(bool get) // add and subtract
- {
- double left = term(get);
-
- for(;;) // ``forever''
- switch (curr_tok) {
- case Lexer::PLUS:
- left += term(true);
- break;
- case Lexer::MINUS:
- left -= term(true);
- break;
- default:
- return left;
- }
- }
-
- int main(int argc, char* argv[])
- {
- // insert pre-defined names:
- table["pi"] = 3.1415926535897932385;
- table["e"] = 2.7182818284590452354;
-
- while (std::cin) {
- Lexer::get_token();
- if (Lexer::curr_tok == Lexer::END) break;
- if (Lexer::curr_tok == Lexer::PRINT) continue;
- std::cout << Parser::expr(false) << '\n';
- }
-
- return Error::no_of_errors;
- }
-